Repository navigation
perf(server): resuming the thread list takes one fewer round trip - #21082
unmanbearpig wants to merge 5 commits into
Conversation
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a focused server-side performance change that coalesces existing reconnect data with its completion marker while preserving ordering and non-marker behavior. Replay buffering is bounded by existing safeguards and supported by extensive lifecycle and chunking tests, with no new capability, schema, deployment, or sensitive-area changes. You can add or adjust custom eligibility rules. Learn more. |
|
Taking over this one. I’ll reduce the tests, rebuild the batching change, and verify replay memory and reconnect latency before pushing to this branch. |
|
Profiling follow-up: #28931 bounds the settled-timestamp cutoff allocation inside shell trimming. It complements the roundtrip reduction here rather than replacing it. Its description explicitly limits the allocation/no-slowdown result to the measured real-index-shaped workload and discloses larger oldest-first CPU regressions. |
Marked thread and shell subscriptions sent
synchronizedin a separate RPC chunk. Effect RPC waits for each chunk ACK, so clients paid another round trip before catch-up completed. Shell resume also acknowledged metadata and replay batches separately.Append completion to the initial chunk. Thread prefixes are already eager; marked shell resumes collect the eligible replay before sending metadata, deltas and completion together. Clients omitting the marker keep the existing streaming path. Prefix references are released after delivery, and the persisted live tail still backfills from the captured high-water mark.
Verification on the maintainer head:
ws.test.ts,rpcInitialItems.memory.test.ts,ShellStream.test.ts, andThreadStream.test.ts; server typecheck and targeted lint/format pass.These are local fixture measurements with delayed ACKs, not physical network RTT or end-user UI timings. The one-event and large-replay cases remove more than just the final marker ACK because metadata/replay now share the prefix.
Memory/projection expansion: 1,000 distinct project shells, each with a 1 or 8 KiB script command written before the cursor, followed by 1,000 small update events (74,890 stored payload bytes). Replay coalescing cannot collapse distinct project IDs. The 8 KiB case serializes about 17 MiB through completion; main splits it, this head sends one ~17 MiB first chunk. Cold snapshots already send a ~17 MiB first chunk on both main and this head. Memory sampling is every 10 ms; the client holds the completion chunk for 100 ms, then closes; the server is measured again after GC. Single runs per cell, no universal memory claim.
The large four-client replay raises observed peak RSS by 141.3 MiB, while sampled peak heap is lower. Head resume is also above head cold snapshot (538.5 vs 442.2 MiB heap, 1093.3 vs 928.4 MiB RSS); main resume is above main cold snapshot too (631.9 vs 494.6 MiB heap). Post-GC heap stays around 202 MiB. An unrelated
server.getConfigRPC sent after the first chunk, while its ACK is held, succeeds during the large four-client run: maximum observed response is 1436.5 → 1713.9 ms; the equivalent head cold snapshot is 1702.3 ms and main cold snapshot is 1919.4 ms. These costs matter alongside the saved ACKs. No retained heap after client close and forced GC, OOM, or protocol timeout was observed in these runs. Larger projected strings and more clients remain unbounded.Exact comparison: main 49b0f96 versus maintainer head 8627f1f. The baseline loads those two production files from main with a Node module hook, leaving checkout and all other code identical.
Not verified: macOS, Windows, iOS, Android, Electron desktop, real relay/tunnel latency, or visual client interactions. This is a server transport change with no UI changes; screenshots do not demonstrate chunk/ACK behavior. The 1,000-event/8 MiB stored-payload eligibility limits do not bound projected bytes or universal process memory.
Original implementation and performance investigation by @unmanbearpig in #21082; contributor commits preserved.
Maintainer takeover: Codex GPT-6 Astra (tests), GPT-6.1 Sol (implementation and integration), GPT-6 Sol and Claude Opus 5.5 (adversarial review), through T3 Code.